﻿Imports System
Imports System.Collections.Generic
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports OMANE.Common.UI
Imports ICSharpCode.AvalonEdit.Highlighting
Imports System.CodeDom.Compiler
Imports System.Linq.Expressions
Imports System.Data
Imports OMANE.Modules.Builder.MSFunctions
Imports OMANE.Modules.Builder.MSExpression
Imports ICSharpCode.AvalonEdit.CodeCompletion
Imports System.ComponentModel
Imports ICSharpCode.NRefactory
Imports ICSharpCode.AvalonEdit.Folding
Imports Microsoft.Practices.Prism.Commands



Partial Public Class ViewTraitement

    Dim codeCompletionWindow As CompletionWindow
    Dim WithEvents textArea As ICSharpCode.AvalonEdit.Editing.TextArea
    Private Shared conn As OleDb.OleDbConnection
    Dim foldingManager As FoldingManager

    Public Sub New()
        MyBase.New()

        Me.InitializeComponent()

        ' Insert code required on object creation below this point.
        codeEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".vb")
        'codeEditor.fol()
        codeEditor.ShowLineNumbers = True
        codeEditor.FontStyle = Windows.FontStyles.Italic
        codeEditor.FontSize = 16
        textArea = codeEditor.TextArea

        foldingManager = foldingManager.Install(codeEditor.TextArea)
        foldingStrategy = New XmlFoldingStrategy()
        foldingStrategy.UpdateFoldings(foldingManager, codeEditor.Document)
        'Me.codeCompletionWindow = New CompletionWindow(codeEditor.TextArea)
        'Dim q = From p As PropertyDescriptor In TypeDescriptor.GetProperties(GetType(TestModel))
        '        Where p.PropertyType Is GetType(MSProperty)
        '        Select New ModelCompletionData(p)
        'Dim q2 = From p As PropertyDescriptor In TypeDescriptor.GetProperties(GetType(TestParams))
        '       Where p.PropertyType.IsSubclassOf(GetType(MSParam))
        '       Select New ModelCompletionData(p)



        'For Each cdata In q
        '    codeCompletionWindow.CompletionList.CompletionData.Add(cdata)
        'Next
        'For Each cdata In q2
        '    codeCompletionWindow.CompletionList.CompletionData.Add(cdata)
        'Next

        'If conn Is Nothing Then
        '    conn = New OleDb.OleDbConnection( _
        '        "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        '        "Data Source=""C:\Users\Consultant Vivei\Documents\Base de données2.accdb""")
        'End If

        'Dim univ As New MSUniverse()
        'univ.Connection = conn
        'Dim mdl = New TestModel(univ)
        'Dim par = New TestParams(univ)
        'univ.MainTable = mdl
        'univ.Params = New MSParam() { _
        '    par.PoidsIdeal, par.TailleIdeal, _
        '    par.AcceptEvryone, par.CoefficientIdeal, par.Correctif}
        ''  Return
        'mdl.Name = "table_principale"
        'par.Correctif.AddProperty(mdl.Sexe)

        'Dim o = mdl.Age + mdl.Poids
        'Dim g = o.ToString()

        'Dim o1 = Sum(mdl.Poids)
        'g = o1.ToString()

        'Dim o2 = Sum(o)
        'g = o2.ToString()

        'Dim sq = mdl.Queries()
        'sq.LogAge = par.Correctif * mdl.Age
        'sq.RapportPoisTaille = mdl.Poids / mdl.Taille
        'sq.OrderBy(sq.RapportPoisTaille)
        'sq.Where(mdl.Sexe = "F")

        'Dim sql = sq.GetSql()

        'Dim oq = mdl.Queries
        'oq.Coeff = par.Correctif
        'oq.Age = mdl.Age
        'oq.Take(10)

        'Dim sqq = oq.GetSql()

        'Dim dt As DataTable = oq.GetData()

    End Sub

    Private Sub codeEditor_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Try
            DataContext.Code = codeEditor.Text

        Catch ex As Exception

        End Try
    End Sub

    Private Sub ViewTraitement_DataContextChanged(ByVal sender As Object, ByVal e As System.Windows.DependencyPropertyChangedEventArgs) Handles Me.DataContextChanged

        Try
            codeEditor.Text = DataContext.Code
        Catch ex As Exception
            codeEditor.Text = ex.ToString()
        End Try
    End Sub

    Private last As Windows.GridLength? = Nothing
    Private Sub utilitiesExpander_Collapsed(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles utilitiesExpander.Collapsed
        If Not utilitiesRow.Height.IsAuto Then
            last = utilitiesRow.Height

        End If
        utilitiesRow.Height = Windows.GridLength.Auto

    End Sub

    Private Sub utilitiesExpander_Expanded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles utilitiesExpander.Expanded
        If last IsNot Nothing Then
            utilitiesRow.Height = last.Value
        End If
    End Sub

    Private Sub textArea_TextEntered(ByVal sender As Object, ByVal e As System.Windows.Input.TextCompositionEventArgs) Handles textArea.TextEntered

        If e.Text = "." Then
            Dim o = 1
            ' codeCompletionWindow.Visibility = Windows.Visibility.Visibl
            Dim win = New CompletionWindow(codeEditor.TextArea)
            'For Each cdata In codeCompletionWindow.CompletionList.CompletionData
            '    win.CompletionList.CompletionData.Add(cdata)
            'Next
            Dim dc = TryCast(DataContext, ViewModelTraitement)
            If dc IsNot Nothing Then
                For Each cdata In dc.GetModelCompletionDatas()
                    win.CompletionList.CompletionData.Add(cdata)
                Next
            End If
            win.Show()
        End If

        If e.Text = vbLf Then

            Dim p = New SnippetParser(SupportedLanguage.VBNet)
            Dim l = codeEditor.Document.GetLineByOffset(codeEditor.CaretOffset).PreviousLine
            If l.Length < 1 Then Return

            Dim txt = codeEditor.Document.GetText(l.Offset, l.Length)

            Dim k = p.Parse(txt)



            Dim cu = TryCast(k, Ast.CompilationUnit)

            If cu IsNot Nothing Then
                If cu.Children.Count < 1 Then Return
                Dim cls = TryCast(cu.Children(0), Ast.TypeDeclaration)
                If cls IsNot Nothing Then
                    Select Case cls.Type
                        Case Ast.ClassType.Class
                            textArea.Document.Insert(codeEditor.CaretOffset, vbCrLf & "End Class")
                        Case Ast.ClassType.Enum
                            textArea.Document.Insert(codeEditor.CaretOffset, vbCrLf & "End Enum")
                        Case Ast.ClassType.Interface
                            textArea.Document.Insert(codeEditor.CaretOffset, vbCrLf & "End Interface")
                        Case Ast.ClassType.Struct
                            textArea.Document.Insert(codeEditor.CaretOffset, vbCrLf & "End Structure")
                        Case Ast.ClassType.Module
                            textArea.Document.Insert(codeEditor.CaretOffset, vbCrLf & "End Module")
                    End Select
                End If

                Return
            End If
            Dim o1 = 1
        End If

        If e.Text = " " Then
            Dim txt = codeEditor.Document.GetText(codeEditor.CaretOffset - 4, 4)
            If txt.ToLower() = " as " Then
                Dim dc = TryCast(DataContext, ViewModelTraitement)

                If dc IsNot Nothing Then
                    Dim win = New CompletionWindow(codeEditor.TextArea)
                    For Each cdata In dc.GetTypeCompletionDatas()
                        win.CompletionList.CompletionData.Add(cdata)
                    Next
                    win.Show()
                End If
            End If
            Dim o = 1
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        If codeEditor.Visibility = Windows.Visibility.Visible Then
            codeEditor.Visibility = Windows.Visibility.Collapsed
            codeFormater.Visibility = Windows.Visibility.Visible
        Else
            codeEditor.Visibility = Windows.Visibility.Visible
            codeFormater.Visibility = Windows.Visibility.Collapsed
        End If


    End Sub
End Class

Public Class ViewModelTraitement
    Inherits ViewModelBase
    Implements IViewModelTabSection

    Dim vmmodelinterne As ViewModelModeleInterne
    Dim vmparametres As ViewModelParametres

    Sub New()

    End Sub

    Public Function GetModelCompletionDatas()
        Dim q = From e In vmparametres.Params
                Select New ModelCompletionData(e.Name, "Params." & e.Name)

        Dim q1 = From e In vmmodelinterne.Model.DefaultEntity.Properties
                 Select New ModelCompletionData(e.Name, "Model." & e.Name)

        Return Enumerable.Union(q, q1)
    End Function

    Private Shared types() As Type
    Private Shared typecompdata As Object
    Public Function GetTypeCompletionDatas()
        If types Is Nothing Then
            types = New Type() {
                GetType(Integer), _
                GetType(Double), _
                GetType(Boolean), _
                GetType(String), _
                GetType(Date), _
                GetType(TimeSpan)}

            typecompdata = (From t In types Select New TypeCompletionData(t)).ToArray()
        End If
        Return typecompdata
    End Function


    Sub New(ByVal vmmodelinterne As ViewModelModeleInterne, ByVal vmparametres As ViewModelParametres)
        Me.vmmodelinterne = vmmodelinterne
        Me.vmparametres = vmparametres
    End Sub

    Public Property Icone As String Implements Common.UI.IViewModelTabSection.Icone
    Public Property Title As String Implements Common.UI.IViewModelTabSection.Title

    Private CodeCompiledFunctor As Func(Of Object)

    Public Property Code As String

    Private _CompileCommand As New DelegateCommand(Of Object)(AddressOf CompileExecute)
    Public ReadOnly Property CompileCommand As DelegateCommand(Of Object)
        Get
            Return _CompileCommand
        End Get
    End Property
    Private Sub CompileExecute(ByVal parameter As Object)


        Dim vb = New VBCodeProvider()

        Dim options = New CompilerParameters()
        options.GenerateExecutable = False
        ' options.GenerateInMemory = False
        options.GenerateInMemory = True
        options.IncludeDebugInformation = True
        '  options.OutputAssembly = "omane.temp.dll"
        options.ReferencedAssemblies.Add( _
            Me.GetType().Assembly.Location)

        Dim importcode = _
            "Option Strict Off" & vbCrLf & _
            "Option Infer On" & vbCrLf & _
            "Option Explicit Off" & vbCrLf & vbCrLf & _
            "Imports System" & vbCrLf & _
            "Imports OMANE.Modules.Builder.MSFunctions" & vbCrLf & _
            "Imports OMANE.Modules.Builder.MSExpression" & vbCrLf & _
            "Imports System.Collections.Generic" & vbCrLf & vbCrLf

        '"Inherits OMANE.Modules.Builder.BaseScriptObject" & vbCrLf & vbCrLf & _
        Dim parameterproperyquery = From p In vmparametres.Params
                                    Select "public property " & p.Name & " as OMANE.Modules.Builder.MSParam"
        Dim parameterscode = _
            "public notinheritable class Parameters" & vbCrLf & vbCrLf & _
            String.Join(vbCrLf, parameterproperyquery.ToArray()) & vbCrLf & vbCrLf & _
            "end class" & vbCrLf & vbCrLf

        Dim modelproperyquery = From p In vmmodelinterne.Model.DefaultEntity.Properties
                                Select "public property " & p.Name & " as OMANE.Modules.Builder.MSProperty"
        Dim modelcode = _
            "public notinheritable class Model" & vbCrLf &
              "   inherits OMANE.Modules.Builder.MSTable" & vbCrLf & vbCrLf & _
              "Sub New(ByVal universe As OMANE.Modules.Builder.MSUniverse)" & vbCrLf &
              "MyBase.New(universe)" & vbCrLf & _
              "End Sub" & vbCrLf & vbCrLf & _
            String.Join(vbCrLf, modelproperyquery.ToArray()) & vbCrLf & vbCrLf & _
            "end class" & vbCrLf & vbCrLf

        Dim finalcode = _
            "public notinheritable class " & Title & "_Class" & vbCrLf & vbCrLf & _
                "friend shared model as Model" & vbCrLf &
                "friend shared params as Parameters" & vbCrLf & vbCrLf & _
                "public shared function Execute() as object" & vbCrLf & vbCrLf & _
                  Code & vbCrLf & _
                "end function" & vbCrLf & vbCrLf & _
            "end class"

        Dim results = vb.CompileAssemblyFromSource(options, importcode & modelcode & parameterscode & finalcode)

        'CompilerErrors = From ce As CompilerError In results.Errors
        '                 Select Ligne = ce.Line,
        '                        Colonne = ce.Column,
        '                        Message = ce.ErrorText,
        '                        Warning = ce.IsWarning

        _CompilerErrors = results.Errors.Cast(Of CompilerError)()
        OnPropertyChanged("CompilerErrorsAll")
        OnPropertyChanged("CompilerErrorsSoft")
        OnPropertyChanged("CompilerErrorsHard")


        If results.Errors.Count = 0 Then
            Windows.MessageBox.Show("Success")
            Me.CodeCompiledFunctor = Nothing

            AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AppDomainCurrentDomainAssemblyResolve
            '  AppDomain.CurrentDomain.Load(results.CompiledAssembly.FullName)
            Dim meth = results.CompiledAssembly.GetType(Title & "_Class", True, True).GetMethod("Execute")
            '  RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AppDomainCurrentDomainAssemblyResolve
            '    AppDomain.CurrentDomain.GetAssemblies()
            Me.CodeCompiledFunctor = [Delegate].CreateDelegate(GetType(Func(Of Object)), meth)
        Else
            If results.Errors.Cast(Of CompilerError).All(Function(ce) ce.IsWarning) Then
                Windows.MessageBox.Show("Success")
            End If
        End If

    End Sub


    Private _ExecuteCodeCommand As New DelegateCommand(Of Object)(AddressOf ExecuteCodeExecute)
    Public ReadOnly Property ExecuteCodeCommand As DelegateCommand(Of Object)
        Get
            Return _ExecuteCodeCommand
        End Get
    End Property
    Private Sub ExecuteCodeExecute(ByVal parameter As Object)
        If CodeCompiledFunctor IsNot Nothing Then
            CodeResult = TryCast(CodeCompiledFunctor.Invoke(), DataTable)
            If CodeResult IsNot Nothing Then
                CodeResult = TryCast(CodeResult, DataTable).DefaultView
            End If
        End If
    End Sub

    Private _CodeResult As Object
    Public Property CodeResult As Object
        Get
            Return _CodeResult
        End Get
        Set(ByVal value As Object)
            OnPropertyChanging("CodeResult")
            _CodeResult = value
            OnPropertyChanged("CodeResult")
        End Set
    End Property

    Private Function AppDomainCurrentDomainAssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As Reflection.Assembly
        If args.Name.Contains("OMANE.Modules.Builder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") Then
            Dim o = 1
            Dim q = From e In AppDomain.CurrentDomain.GetAssemblies()
                     Where e.FullName.Contains("OMANE.Modules.Builder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
                     Select e

            Return q.FirstOrDefault()
        End If

        Return Nothing
    End Function

    Private _CompilerErrors As IEnumerable(Of CompilerError)
    Public ReadOnly Property CompilerErrorsAll As IEnumerable
        Get
            If _CompilerErrors Is Nothing Then Return Nothing
            Return _CompilerErrors
        End Get
    End Property
    Public ReadOnly Property CompilerErrorsSoft As IEnumerable
        Get
            If _CompilerErrors Is Nothing Then Return Nothing
            Return _CompilerErrors.Where(Function(ce) ce.IsWarning)
        End Get
    End Property
    Public ReadOnly Property CompilerErrorsHard As IEnumerable
        Get
            If _CompilerErrors Is Nothing Then Return Nothing
            Return _CompilerErrors.Where(Function(ce) Not ce.IsWarning)
        End Get
    End Property
End Class

Public Class ModelTraitement

End Class

Public Class Model

End Class

Public Class BaseScriptObject

    Private Shared _modelexpanded As Dynamic.ExpandoObject
    Private Shared _params As TestParams
    Private Shared _model As TestModel
    Private Shared _universe As MSUniverse

    <Runtime.CompilerServices.Dynamic()> _
    Public Shared ReadOnly Property modelExpanded As Object
        Get
            If _modelexpanded Is Nothing Then
                _modelexpanded = New Dynamic.ExpandoObject()
            End If
            Return _modelexpanded
        End Get
    End Property

    Private Shared Sub initUnivers()
        If _universe Is Nothing Then
            Dim conn = New OleDb.OleDbConnection( _
                    "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                    "Data Source=""C:\Users\Consultant Vivei\Documents\Base de données2.accdb""")

            _universe = New MSUniverse()
            _universe.Connection = conn

            _model = New TestModel(_universe)
            _params = New TestParams(_universe)
            _universe.MainTable = _model

            _universe.Params = New MSParam() { _
                _params.PoidsIdeal, _params.TailleIdeal, _
                _params.AcceptEvryone, _params.CoefficientIdeal, _params.Correctif}
            '  Return
            _model.Name = "table_principale"
        End If
    End Sub

    Public Shared ReadOnly Property model As TestModel
        Get
            initUnivers()
            Return _model
        End Get
    End Property

    Public Shared ReadOnly Property params As TestParams
        Get
            initUnivers()
            Return _params
        End Get
    End Property
End Class

Public Structure Lazy(Of T As Structure)
    Private initializer As Func(Of T)
    Private value As T?

    Sub New(ByVal value As T)
        Me.initializer = Nothing
        Me.value = value
    End Sub
    Sub New(ByVal initializer As Func(Of T))
        Me.initializer = initializer
        Me.value = Nothing
    End Sub
End Structure

Public Class Matrix(Of T As Structure)

End Class
Public Class DataList


End Class
Public Class Sheet(Of T)

End Class

Public Class ModelCompletionData
    Implements ICompletionData

    'Dim Properties As PropertyDescriptor()


    'Sub New(ByVal mdlType As Type)
    '    Dim q = From p As PropertyDescriptor In TypeDescriptor.GetProperties(mdlType)
    '            Where p.PropertyType Is GetType(BaseModelProperty)
    '            Select p


    '    Me.Properties = q.ToArray()
    'End Sub

    Dim [Property] As PropertyDescriptor
    Dim __name As String
    Dim __show As String

    Sub New(ByVal p As PropertyDescriptor)
        Me.Property = p
    End Sub
    Sub New(ByVal __name As String, ByVal __show As String)
        Me.Property = Nothing
        Me.__name = __name
        Me.__show = __show

    End Sub

    Public Sub Complete(ByVal textArea As ICSharpCode.AvalonEdit.Editing.TextArea, ByVal completionSegment As ICSharpCode.AvalonEdit.Document.ISegment, ByVal insertionRequestEventArgs As System.EventArgs) Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Complete
        textArea.Document.Replace(completionSegment, Text)
    End Sub
    Public ReadOnly Property Content As Object Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Content
        Get
            If [Property] Is Nothing Then
                Return __show
            End If
            Return [Property].Name & " As " & [Property].PropertyType.Name
        End Get
    End Property
    Public ReadOnly Property Description As Object Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Description
        Get
            If [Property] Is Nothing Then
                Return __show
            End If
            Return Me.Property.Description
        End Get
    End Property
    Public ReadOnly Property Image As System.Windows.Media.ImageSource Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Image
        Get
            Return Nothing
        End Get
    End Property
    Public ReadOnly Property Priority As Double Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Priority
        Get
            Return 0.0
        End Get
    End Property
    Public ReadOnly Property Text As String Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Text
        Get
            If [Property] Is Nothing Then
                Return __name
            End If
            Return Me.Property.Name
        End Get
    End Property
End Class


Public Class TypeCompletionData
    Implements ICompletionData

    Dim t As Type

    Sub New(ByVal t As Type)
        Me.t = t
    End Sub



    Public Sub Complete(ByVal textArea As ICSharpCode.AvalonEdit.Editing.TextArea, ByVal completionSegment As ICSharpCode.AvalonEdit.Document.ISegment, ByVal insertionRequestEventArgs As System.EventArgs) Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Complete
        If t Is GetType(Integer) Then
            textArea.Document.Replace(completionSegment, "Integer ")
            Return
        End If
        If t Is GetType(Date) Then
            textArea.Document.Replace(completionSegment, "Date ")
            Return
        End If
        textArea.Document.Replace(completionSegment, t.Name & " ")
    End Sub
    Public ReadOnly Property Content As Object Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Content
        Get
            Return t.Name
        End Get
    End Property
    Public ReadOnly Property Description As Object Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Description
        Get
            Return t.FullName & " in " & t.Assembly.FullName
        End Get
    End Property
    Public ReadOnly Property Image As System.Windows.Media.ImageSource Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Image
        Get
            Return Nothing
        End Get
    End Property
    Public ReadOnly Property Priority As Double Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Priority
        Get
            Return 0.0
        End Get
    End Property
    Public ReadOnly Property Text As String Implements ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData.Text
        Get
            Return t.Name
        End Get
    End Property
End Class

Public Class Folding
    Inherits AbstractFoldingStrategy



    Public Overrides Function CreateNewFoldings(ByVal document As ICSharpCode.AvalonEdit.Document.TextDocument, ByRef firstErrorOffset As Integer) As System.Collections.Generic.IEnumerable(Of ICSharpCode.AvalonEdit.Folding.NewFolding)

    End Function
End Class